package org.egrit;

import java.awt.Point;

/**
 * Iterates over cell positions within a target {@linkplain IGridBounds}.
 * 
 * @author michael
 */
public class GridBoundsIterator implements IGridIterator {
    protected final boolean emptyBounds;
    protected final Point pos;
    protected final Point minPos;
    protected final Point maxPos;
    protected boolean finished;

    public GridBoundsIterator(IGridBounds bounds) {
        if (bounds == null || bounds.isEmpty()) {
            emptyBounds = true;
            finished = true;
            pos = minPos = maxPos = new Point();
            
        } else {
            emptyBounds = false;
            finished = false;
            minPos = new Point(bounds.getMinGridX(), bounds.getMinGridY());
            maxPos = new Point(bounds.getMaxGridX(), bounds.getMaxGridY());
            pos = new Point(minPos);
        }
    }
    
    
    @Override
    public boolean isEmpty() {
        return emptyBounds;
    }

    @Override
    public IGridBounds getGridBounds() {
        if (emptyBounds) {
            return GridBoundsFactory.create();
        } else {
            return GridBoundsFactory.create(minPos.x, maxPos.x, minPos.y, maxPos.y);
        }
    }

    /**
     * {@inheritDoc}
     * Note that if the target bounds are empty, this will always 
     * return {@code Point(0, 0)}.
     */
    @Override
    public Point getPos() {
        return new Point(pos);
    }

    @Override
    public boolean hasNext() {
        if (emptyBounds || finished) {
            return false;
        }
                
        finished = !(pos.x < maxPos.x || pos.y < maxPos.y);
        return !finished;
    }
    
    @Override
    public boolean next() {
        if (!hasNext()) {
            return false;
        }
        
        boolean moved = true;
        
        if (pos.x < maxPos.x) {
            pos.x++;
        } else if (pos.y < maxPos.y) {
            pos.x = minPos.x;
            pos.y++;
        } else {
            moved = false;
        }
        
        return moved;
    }

    @Override
    public void reset() {
        if (!emptyBounds) {
            finished = false;
            pos.setLocation(minPos);
        }
    }
    
}
